package com.tgit.sso.core.conf;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tgit.sso.core.common.ResponseT;
import com.tgit.sso.core.util.JacksonUtil;
import com.tgit.sso.core.util.JedisUtil;
import com.tgit.sso.core.util.SsoLoginHandlerUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * app-基于token方式的单点登录过滤器配置-用于客户端
 * @author 范再军
 * 2018年9月12日
 */
public class SsoTokenFilter extends HttpServlet implements Filter {

	private static final long serialVersionUID = 6405105521693341988L;

	private static Logger LOGGER = LoggerFactory.getLogger(SsoTokenFilter.class);

	//sso-server域名地址-跳转地址
	private String ssoServer;
	//sso-server判断通断地址-私有云部署内网配置地址 
	private String ssoConnectUrl;
	//sso-客户端登出地址
	private String logoutPath;
	//redis地址
	private String redisAddress;
	//redis密码
	private String redisPassword;
	//是否走单点登录地址 ssoFlag="sso"走单点登录，不配置为null就是不走sso
	private String ssoFlag;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    	/**
		 * 初始化,工程启动会被执行
		 */
		ssoServer = filterConfig.getInitParameter(SsoConf.SSO_SERVER);
		if (ssoServer != null && ssoServer.trim().length() > 0) {
			logoutPath = filterConfig.getInitParameter(SsoConf.SSO_LOGOUT_PATH);
			redisAddress = filterConfig.getInitParameter(SsoConf.REDIS_ADDRESS);
			ssoConnectUrl = filterConfig.getInitParameter(SsoConf.SSO_CONNECT_URL);
			ssoFlag = filterConfig.getInitParameter(SsoConf.SSO_FLAG);
			//如果配置了redis就加入
			if(!StringUtils.isBlank(this.redisAddress)) {
	    		if(StringUtils.isBlank(this.redisPassword)) {
	    			JedisUtil.init(redisAddress);
	    			LOGGER.info("REDIS初始化非密码模式配置");
	    		}else {
	    			JedisUtil.init(redisAddress, redisPassword);    
	    			LOGGER.info("REDIS初始化密码模式配置");
	    		}
	    	}else {
	    		LOGGER.error("REDIS没有配置");
	    	}
		}
		LOGGER.info("SsoFilter init" + ssoServer + ":" + ssoServer);
    }

	/**
	 * 提供给实现类调用
	 * @param ssoServer
	 * @param ssoConnectUrl
	 * @param logoutPath
	 * @param clientServer
	 * @param redisAdress
	 * @param ssoFlag
	 */
	public void init(String ssoServer,String ssoConnectUrl,String logoutPath,String redisAddress,String redisPassword,String ssoFlag) {
		this.ssoServer=ssoServer;
		this.ssoConnectUrl=ssoConnectUrl;
		this.logoutPath=logoutPath;
		this.redisAddress=redisAddress;
		this.ssoFlag=ssoFlag;
		//如果配置了redis就加入
		if(!StringUtils.isBlank(this.redisAddress)) {
    		if(StringUtils.isBlank(this.redisPassword)) {
    			JedisUtil.init(redisAddress);
    			LOGGER.info("REDIS初始化非密码模式配置");
    		}else {
    			JedisUtil.init(redisAddress, redisPassword);    
    			LOGGER.info("REDIS初始化密码模式配置");
    		}
    	}else {
    		LOGGER.error("REDIS没有配置");
    	}
		LOGGER.info("SsoFilter init" + ssoServer + ":" + ssoServer);
	}
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    	if(!ssoFlag.isEmpty() && "sso".equals(ssoFlag)) {
	        HttpServletRequest req = (HttpServletRequest) request;
	        HttpServletResponse res = (HttpServletResponse) response;
	        String servletPath = ((HttpServletRequest) request).getServletPath();
	        String token = SsoLoginHandlerUtils.getByHeaderToken(req);
	        SsoUser ssoUser = SsoLoginHandlerUtils.loginCheck(token);
	        
	        //登出过滤器
	        if (logoutPath != null && logoutPath.trim().length() > 0 && logoutPath.equals(servletPath)) {
	        	//判断用户是否为空，不为空做登出操作，如果为空，无需做登出操作
	            if (ssoUser != null) {
	            	SsoLoginHandlerUtils.logout(token);
	            }
	            //设置响应体数据为json格式数据
	            res.setStatus(HttpServletResponse.SC_OK);
	            res.setContentType(SsoConf.APPLICATION_JSON_CHARSET_UTF_8);
	            res.getWriter().println(JacksonUtil.writeValueAsString(new ResponseT<Object>(ResponseT.LOGOUT_CODE, SsoConf.LOGOUT_SUCCESS)));
	            return;
	        }
	        // 如果redis的token过期，需要重新登录获取token信息，
            // 伪造token，ssoUser也会得不到
	        if (ssoUser == null) {
	            //响应设置json格式数据
	            res.setStatus(HttpServletResponse.SC_OK);
	            res.setContentType(SsoConf.APPLICATION_JSON_CHARSET_UTF_8);
	            res.getWriter().println(JacksonUtil.writeValueAsString(new ResponseT<Object>(ResponseT.TOKEN_CODE, SsoConf.ERROR_SSO.TOKEN_ERROR_MSG)));
	            return;
	        }
	    	// 判断服务器联通状态,服务器不连通，清除redis数据
			if (!SsoConf.isReachableUrl(this.ssoConnectUrl)) {
				//判断用户是否为空，不为空做登出操作，如果为空，无需做登出操作
	            if (ssoUser != null) {
	            	SsoLoginHandlerUtils.logout(token);
	            }
				res.setStatus(HttpServletResponse.SC_OK);
	            res.setContentType(SsoConf.APPLICATION_JSON_CHARSET_UTF_8);
	            res.getWriter().println(JacksonUtil.writeValueAsString(new ResponseT<Object>(ResponseT.SERVER_CODE, SsoConf.LOGOUT_SUCCESS)));
	            return;
			}
	        //嵌入sso用户信息	
	        request.setAttribute(SsoConf.SSO_USER, ssoUser);
    	}
        //已经登录，继续操作
        chain.doFilter(request, response);
        return;
    }


}
